package com.glacier.yuyuan.common.aspectj;

import cn.hutool.core.util.StrUtil;
import com.glacier.common.core.annotation.DataScope;
import com.glacier.common.core.constant.CommonConstant;
import com.glacier.common.core.constant.DictEnum;
import com.glacier.common.core.domain.Expandable;
import com.glacier.yuyuan.common.constant.DataScopeConstants;
import com.glacier.yuyuan.common.utils.SecurityUtils;
import com.glacier.yuyuan.modules.admin.sys.domain.Role;
import com.glacier.yuyuan.modules.admin.sys.domain.User;
import com.glacier.yuyuan.modules.admin.sys.mapper.RoleMapper;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * date 2023-01-20 20:28
 * 数据权限 设置
 *
 * @author glacier
 * @version 1.0.0
 */
@Aspect
@Order(1)
@Component
public class DataScopeAspect {

    private static final Logger LOGGER = LoggerFactory.getLogger(DataScopeAspect.class);

    private RoleMapper roleMapper;

    @Autowired
    public void setRoleMapper(RoleMapper roleMapper) {
        this.roleMapper = roleMapper;
    }

    /**
     * 前置通知
     *
     * @param point     交织点
     * @param dataScope 注解
     */
    @Before("@annotation(dataScope)")
    public void dsBefore(JoinPoint point, DataScope dataScope) {
        // 获取参数
        Object[] args = point.getArgs();
        if (null == args || args.length == 0) {
            LOGGER.warn("标注数据权限的方法参数不能为空！");
            return;
        }

        Arrays.stream(args)
                .filter(arg -> arg instanceof Expandable)
                .findFirst()
                .ifPresentOrElse(e -> {
                    handle(((Expandable) e).getParams(), SecurityUtils.getCurrentUser(), dataScope);
                }, () -> LOGGER.warn("@annotation(dataScope) 没有符合的参数"));
    }

    /**
     * 处理数据权限
     *
     * @param map
     * @param user
     * @param dataScope
     */
    private void handle(final Map<String, Object> map, final User user, DataScope dataScope) {
        // 先清空
        map.put(CommonConstant.SCOPE, "");
        if (user == null || user.getId() == null) {
            map.put(CommonConstant.SCOPE, StrUtil.format(
                    " AND {}.id = #{params.id_} ", dataScope.alias()));
            // id 为''
            map.put("id_", "");
            return;
        }
        // 设置当前用户id
        map.put(CommonConstant.CURRENT, user.getId());
        // 查询当前用户角色
        List<Role> roleList = roleMapper.findByUserId(user.getId());

        if (roleList.isEmpty()) {
            // 本人
            map.put(CommonConstant.SCOPE, StrUtil.format(
                    " AND {}.createBy = #{params.userId_} ", dataScope.alias()));
            map.put("userId_", user.getId());
            return;
        }
        // 获取用户的数据权限
        StringBuilder scopeBuilder = new StringBuilder();
        Set<String> scopes = new HashSet<>();
        int i = 0;
        for (Role role : roleList) {
            // 全部权限，则跳出循环
            if (DataScopeConstants.DATA_SCOPE_ALL.equals(role.getDataScope())) {
                scopeBuilder = new StringBuilder();
                break;
            }
            // 自定义数据权限
            if (DataScopeConstants.DATA_SCOPE_CUSTOM.equals(role.getDataScope())) {
                scopeBuilder.append(StrUtil.format(
                        " OR EXISTS ( SELECT 1 FROM sys_role_office sr_ WHERE {}.{}=sr_.office_id AND sr_.role_id = #{params.roleId{}_} ) ",
                        dataScope.alias(), dataScope.column(), i));
                map.put("roleId" + i + "_", role.getId());
            }
            // 已经存在，则跳过
            if (scopes.contains(role.getDataScope())) {
                continue;
            }
            if (DataScopeConstants.DATA_SCOPE_OFFICE_AND_CHILD.equals(role.getDataScope())) {
                scopeBuilder.append(StrUtil.format(
                        " OR EXISTS ( SELECT 1 FROM sys_office so_ WHERE so_.del_flag='{}' AND {}.{}=so_.id AND so_.parent_ids like #{params.officeIdLike_} ) ",
                        DictEnum.DATA_NORMAL.getCode(), dataScope.alias(), dataScope.column()));
                map.put("officeIdLike_", CommonConstant.PERCENT
                        + CommonConstant.HALF_CORNER_COMMA
                        + user.getOfficeId()
                        + CommonConstant.HALF_CORNER_COMMA
                        + CommonConstant.PERCENT);
            } else if (DataScopeConstants.DATA_SCOPE_OFFICE_SELF.equals(role.getDataScope())) {
                scopeBuilder.append(StrUtil.format(" OR {}.{} = #{params.officeId_} ",
                        dataScope.alias(), dataScope.column()));
                map.put("officeId_", user.getOfficeId());
            } else {
                scopeBuilder.append(StrUtil.format(" OR {}.create_by = #{params.userId_} ", dataScope.alias()));
                map.put("userId_", user.getId());
            }
            // 索引自增
            i++;
            scopes.add(role.getDataScope());
        }
        if (!scopeBuilder.toString().isBlank()) {
            map.put(CommonConstant.SCOPE, " AND (" + scopeBuilder.substring(4) + ")");
        }
    }
}
